
#if defined(_GNUC) && defined(_arm)



#include <asm.h>

.global C_SYMBOL(memcpy)

C_SYMBOL(memcpy):

arg_0=  0
arg_4=  4

    STMFD   SP!, {R4-R12,LR}

_START_:
    MOV R12, R0
    CMP R2, #0

    BLE _DONE_
    MOV R6, R2                              //R6 = buffer size
    ADD R7, R0, #3                          //R0 = destination pointer
    BIC R7, R7, #3                          //Ceiling R7 ADDRESS to 4 bytes aligned, suppose N bytes jumped
    SUB R7, R7, R0                          //
    CMP R7, #0                              //Compare to see if R7 is originally 4 bytes aligned
    BEQ _lc030_000669_                      //if so jump to _lc030_000669_

_Less_Than_32_:
    LDRB   R3 ,[R1], #1                   //R1 = Source pointer, LOAD 1 byte

    CMP R7, R6                              //
    MOVGT   R7, R6                          //Let R7 be min(N , size)
    SUB R6, R6, R7                          //Let R6 be size - N

_Process_Step_N_header_:
    SUBS    R7, R7, #1                      //N-- and modify CPSR
    STRB    R3 ,[R0], #1                   //SAVE 1 byte
    LDRGTB  R3 ,[R1], #1                 //if size > N, LOAD 1 byte again

    BGT _Process_Step_N_header_             //and then jump to _Process_Step_N_header_
    CMP R6, #0
    BEQ _DONE_                              //if R6 = size - N == 0 jump to _DONE_

_lc030_000669_:
    SUBS    R6, R6, #0x20                   //R6 -= 32 bytes
    ADDMI   R7, R6, #0x20
    ADDMI   R6, R6, #0x20
    BMI _Less_Than_32_                      //jumpt to _Less_Than_32_ if less than 32 bytes
    TST R1, #3
    ADDNE   R7, R6, #0x20
    ADDNE   R6, R6, #0x20
    BNE _Less_Than_32_                        //if pSrc is not 4 bytes aligned, jump to _Less_Than_32_

    LDMIA   R1!, {R2-R5}

_Loop_Aligned8_:
#ifdef _wmmx
    PLD [R1,#0x20]
#endif

    SUBS    R6, R6, #0x20

    STMIA   R0!, {R2-R5}
    LDMIA   R1!, {R8-R11}
    LDMGEIA R1!, {R2-R5}
    STMIA   R0!, {R8-R11}

    BGE _Loop_Aligned8_

    ADDS    R6, R6, #0x20
    BEQ _DONE_
    MOVGT   R7, R6
    BGT _Less_Than_32_
    B _DONE_

_DONE_:
    MOV     R0, R12
    LDMFD   SP!, {R4-R12,PC}

#endif
